发布在网络上,权当备份,程序还未完成。。。
使用的是Air724作为4G数据透传

插座上使用ESP32作为客户端,air724与esp32通信使用的是hc-12

有一个小小的缺点,就是使用hc-12发数据时会丢包,不知道有么有小伙伴有更好的解决办法~~
贴上未完成的程序代码,写的程序比较拉跨,勿喷~以下是4g透传模块的程序:
main.lua:
PROJECT = "CLIENT" VERSION = "1.0.0" require "sys" require 'study' --启动系统框架 sys.init(1, 0) sys.run()
study.lua:
module(..., package.seeall)
require 'sys'
require 'mqtt'
require 'log'
require 'audio'
require 'pm'
require 'socket'
require 'uart'
require 'net'
local UART_ID = 1
local uartData = nil
local mqttClient = nil
local mqttUsername = '10001'
local mqttPort = 1883
local mqttAddress = 'xxx.cn1.mqtt.chat'
local mqttPassword = 'xxx'
local mqttClientId = 'xxx@xxx'
local mqttPublish = 'julecn/esp32/recv'
local mqttSubscribe = 'julecn/esp32/data'
local function uartRead()
local data = ''
--底层core中,串口收到数据时:
--如果接收缓冲区为空,则会以中断方式通知Lua脚本收到了新数据;
--如果接收缓冲器不为空,则不会通知Lua脚本
--所以Lua脚本中收到中断读串口数据时,每次都要把接收缓冲区中的数据全部读出,
--这样才能保证底层core中的新数据中断上来,此read函数中的while语句中就保证了这一点
while true do
data = uart.read(UART_ID,999999999)
if not data or string.len(data) == 0 then break end
log.info("read Data:",data)
uartData = data
end
end
-- local function uartWrite(s)
-- uart.write(UART_ID,s.."\r\n")
-- end
local function uartWriteOk()
log.info('uartWriteOk')
end
function uartInit()
sys.wait(5000)
uart.on(UART_ID,"sent",uartWriteOk)
uart.on(UART_ID,"receive",uartRead)
uart.setup(UART_ID,115200,8,uart.PAR_ODD,uart.STOP_1,nil,1)
end
function getMessage()
while true do
local r, data, param = mqttClient:receive(10, "pub_msg")
if r and data.payload then
-- uartWrite(data.payload)
uart.write(UART_ID,data.payload.."\r\n")
log.info("subscribe:", data.payload or "nil")
elseif data == "pub_msg" then
log.info("这是收到了订阅的消息和参数显示:", data, param)
elseif data == "timeout" then
-- log.info("这是等待超时主动上报数据的显示!")
if uartData then
log.info("publish data:",uartData)
mqttClient:publish('julecn/esp32/recv',uartData,0)
uartData = nil
end
else
log.info('连接断开,重启中……',r,data,param)
sys.restart('MQTT断开,触发重启')
break
end
end
end
function subscribe()
log.info('正在订阅消息')
sys.wait(100)
if mqttClient:subscribe("julecn/esp32/data", 1) then
log.info('消息订阅成功')
getMessage()
else
log.info('消息订阅失败')
connect()
end
end
function connect()
local err = 0
while not socket.isReady() do
log.info('网络未就绪,等待中…')
log.info(net.getNetMode())
log.info(net.getState())
err = err + 1
if err >= 45 then
sys.restart('网络无法连接,触发重启')
end
sys.wait(1000)
end
log.info('初始化已完成,准备连接网络')
sys.wait(5000)
mqttClient = mqtt.client(mqttClientId,60,mqttUsername,mqttPassword)
while true do
if mqttClient:connect(mqttAddress,mqttPort,"tcp") then
log.info('网络连接成功')
sys.wait(100)
subscribe()
break;
else
log.info('网络连接失败,重启中…')
sys.restart('网络连接失败,触发重启')
end
end
end
function start()
sys.taskInit(uartInit)
sys.taskInit(connect)
end
sys.timerStart(function()
start()
end,5000)
插座的使用的ESP32:
boot.py
from machine import UART
import time
import json
from jule import app
import _thread
# 4、15 上级接口
# 22、23 下级接口
def start():
app.p = UART(1, baudrate = 115200, bits = 8, parity = None, rx = 4, tx = 15, timeout = 10,stop = 1)
try:
app.start()
print('service start…')
while app.ISRUNING():
if(app.p.any()):
rs = app.uartProcessor(app.p.read())
if(isinstance(rs,dict)):
app.p.write(json.dumps(rs))
print('回复数据:{}'.format(rs))
except KeyboardInterrupt:
print('中断执行')
except Exception as e:
print(e)
start()
jule.py
import os
import re
import sys
import json
import time
import upip
import array
import socket
import struct
import network
import _thread
import ubluetooth
from machine import Timer,UART
from machine import PWM, Pin
from umqtt.simple import MQTTClient
class ble:
UART_UUID = ubluetooth.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
RX_UUID = ubluetooth.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E")
TX_UUID = ubluetooth.UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E")
_ADV_TYPE_FLAGS = const(0x01)
_ADV_TYPE_NAME = const(0x09)
_ADV_TYPE_UUID16_COMPLETE = const(0x3)
_ADV_TYPE_UUID32_COMPLETE = const(0x5)
_ADV_TYPE_UUID128_COMPLETE = const(0x7)
_ADV_TYPE_UUID16_MORE = const(0x2)
_ADV_TYPE_UUID32_MORE = const(0x4)
_ADV_TYPE_UUID128_MORE = const(0x6)
_ADV_TYPE_APPEARANCE = const(0x19)
_IRQ_CENTRAL_CONNECT = const(1 << 0) #中央设备已经连接到这个外围设备
_IRQ_CENTRAL_DISCONNECT = const(1 << 1) #中央设备已与此外围设备断开
_IRQ_GATTS_WRITE = const(1 << 2) #中央设备已写入此特征或描述符
_IRQ_GATTS_READ_REQUEST = const(1 << 3) # 中央设备已发出读请求.
# Note: 这是一个硬件IRQ,返回None来拒绝读操作 ¥
# Note: 这事件不支持 ESP32.
_IRQ_SCAN_RESULT = const(1 << 4) #一次扫描的结果
_IRQ_SCAN_COMPLETE = const(1 << 5) #扫描持续时间已完成或手动停止
_IRQ_PERIPHERAL_CONNECT = const(1 << 6) #gap_connect()连接成功
_IRQ_PERIPHERAL_DISCONNECT = const(1 << 7) #已连接的外围设备已断开
_IRQ_GATTC_SERVICE_RESULT = const(1 << 8) #调用gattc_discover_services()找到的每个服务
_IRQ_GATTC_CHARACTERISTIC_RESULT = const(1 << 9) #调用gattc_discover_services()找到的每个特征
_IRQ_GATTC_DESCRIPTOR_RESULT = const(1 << 10) #调用gattc_discover_descriptors()找到的每个描述符
_IRQ_GATTC_READ_RESULT = const(1 << 11) #gattc_read() 已完成
_IRQ_GATTC_WRITE_STATUS = const(1 << 12) #gattc_write() 已完成
_IRQ_GATTC_NOTIFY = const(1 << 13) #外围设备已发出通知请求
_IRQ_GATTC_INDICATE = const(1 << 14) #外围设备发出指示请求
UART_SERVICE = (
UART_UUID,(
(TX_UUID, ubluetooth.FLAG_NOTIFY,),
(RX_UUID, ubluetooth.FLAG_WRITE,),
),
)
def __init__(self,name = 'JULE-IOT'):
self._bt = ubluetooth.BLE()
self.conn_handle = None
self.write = self._bt.gatts_write
self.read = self._bt.gatts_read
self.notify = self._bt.gatts_notify
self._bt.active(False)
print("activating ble...")
self._bt.active(True)
print("ble activated")
self._bt.config(rxbuf = rxbuf)
self._bt.irq(self.irq)
self.register_services()
self.adv_payload = self.advertising_payload(name = name, services = (self.UART_UUID), appearance = const(768))
self.advertise()
def advertising_payload(self,limited_disc = False, br_edr = False, name = None, services = None, appearance = 0):
payload = bytearray()
def _append(adv_type, value):
nonlocal payload
payload += (struct.pack('BB', len(value) + 1, adv_type) + value)
_append(const(0x01), struct.pack('B', (0x01 if limited_disc else 0x02) + (0x00 if br_edr else 0x04)))
if name:
_append(const(0x09), name)
_append(_ADV_TYPE_APPEARANCE, struct.pack('<h', appearance))
return payload
def advertise(self, interval_us = 500000):
self._bt.gap_advertise(None)
self._bt.gap_advertise(interval_us, adv_data = self.adv_payload, resp_data = None)
print("advertising...")
def register_services(self):
((self.tx_handle,self.rx_handle,),) = self._bt.gatts_register_services((self.UART_SERVICE,))
def irq(self,event,data):
if event == _IRQ_CENTRAL_CONNECT:
self.__conn_handle, addr_type, addr = data
print('已连接:{}'.format(data))
elif event == _IRQ_CENTRAL_DISCONNECT:
print('中央设备已与此外围设备断开')
conn_handle, addr_type, addr = data
self.__advertise()
# elif event == _IRQ_GATTS_WRITE:
elif event == 3:
conn_handle, value_handle = data
read = self.__read(self.__rx_handle).decode('utf-8')
print('中央设备已写入此特征或描述符:{}'.format(read))
# if conn_handle == self.__conn_handle and value_handle == self.__rx_handle:
elif event == _IRQ_GATTS_READ_REQUEST:
print('中央设备已发出读请求')
conn_handle, attr_handle = data
elif event == _IRQ_SCAN_RESULT:
print('一次扫描的结果')
addr_type, addr, connectable, rssi, adv_data = data
elif event == _IRQ_SCAN_COMPLETE:
print('扫描持续时间已完成或手动停止')
elif event == _IRQ_PERIPHERAL_CONNECT:
print('gap_connect()连接成功')
conn_handle, addr_type, addr = data
elif event == _IRQ_PERIPHERAL_DISCONNECT:
print('已连接的外围设备已断开')
conn_handle, addr_type, addr = data
elif event == _IRQ_GATTC_SERVICE_RESULT:
print('调用gattc_discover_services()找到的每个服务')
conn_handle, start_handle, end_handle, uuid = data
elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT:
print('调用gattc_discover_services()找到的每个特征')
conn_handle, def_handle, value_handle, properties, uuid = data
elif event == _IRQ_GATTC_DESCRIPTOR_RESULT:
print('调用gattc_discover_descriptors()找到的每个描述符')
conn_handle, dsc_handle, uuid = data
elif event == _IRQ_GATTC_READ_RESULT:
print('gattc_read() 已完成')
conn_handle, value_handle, char_data = data
elif event == _IRQ_GATTC_WRITE_STATUS:
print('gattc_write() 已完成')
conn_handle, value_handle, status = data
elif event == _IRQ_GATTC_NOTIFY:
print('外围设备已发出通知请求')
conn_handle, value_handle, notify_data = data
elif event == _IRQ_GATTC_INDICATE:
print('外围设备发出指示请求')
conn_handle, value_handle, notify_data = data
else:
print(event,data)
class config:
__default = {
'wifi':{
'ssid':'JULE-IOT',
'password':'12345678',
'active':True
},
'mqtt':{
'autoConnect':False,
'clientId':None,
'server':None,
'user':None,
'passsword':None,
'keeplive':60,
'ssl':False,
'ssl_params':{},
'subscribe':[]
}
}
__config = {}
def __init__(self):
try:
os.mkdir('/config')
except:
pass
# 读取文件合并数据
for i in os.listdir('/config'):
if i.endswith('.ini') == False:
continue
filename = i.rstrip('ini').rstrip('.')
try:
file = open('/config/' + i,'r')
conf = json.loads(file.read())
config.__config[filename] = conf
file.close()
except:
default = {}
if filename in config.__default:
default = config.__default[filename]
file = open('/config/' + i,'w')
file.write(json.dumps(default))
file.close()
print('合并默认配置',filename)
# 保存默认配置信息
for i in config.__default:
if i not in config.__config:
try:
file = open('/config/' + i + '.ini','w')
file.write(json.dumps(config.__default[i]))
file.close()
config.__config[i] = config.__default[i]
except Exception as e:
print('保存默认配置异常',e)
print('config info:{}'.format(config.__config))
def get(self,key,default = None):
if key == None:
return config.__config
key = key.split('.',2)
try:
file = open('/config/' + key[0] + '.ini','r')
v = json.loads(file.read())
config.__config[key[0]] = v
file.close()
if len(key) == 2 and key[1] in v:
return v[key[1]]
else:
return v
except:
return default
def set(self,key,value):
key = key.split('.',2)
try:
if len(key) == 2:
config.__config[key[0]][key[1]] = value
else:
config.__config[key[0]] = value
file = open('/config/' + key[0] + '.ini','w')
file.write(json.dumps(config.__config[key[0]]))
file.close()
return True
except Exception as e:
print('系统文件异常',e)
def delete(self,key):
key = key.split('.',2)
try:
if len(key) == 2 and key[0] in config.__config:
del config.__config[key[0]][key[1]]
file = open('/config/' + key[0] + '.ini','w')
file.write(json.dumps(config.__config[key[0]]))
file.close()
else:
del config.__config[key[0]]
try:
os.remove('/config/' + key[0] + '.ini')
except:
pass
return True
except Exception as e:
print('删除文件配置异常',e)
class system:
def __init__(self):
pass
def error(self,data):
pass
class device:
def __init__(self):
pass
def __getattribute__(self, name):
pass
def __setattr__(self, name, value):
pass
def __delattr__(self, name):
pass
def factoryReset(self,data):
print('factory reset...')
try:
os.rmdir('/config')
except Exception as e:
pass
print('reboot...')
self.reboot(data)
def reboot(self,data):
import machine
machine.reset()
def sub(self,data):
print(data)
app.subDevice.write(json.dumps(data))
def scanWifi(self,data):
app.wlan = network.WLAN(network.STA_IF)
app.wlan.active(True)
scan = app.wlan.scan()
print('SCAN WIFI:{}'.format(scan))
response = {"action":"device.scanWifi","data":scan}
return response
def info(self,data):
print('WIFI IP:{}'.format(app.wlan.ifconfig()[0]))
response = {"action":"device.info","data":{"vlan_wifi":app.wlan.ifconfig()[0]}}
return response
def wlanStatus(self,data):
status = app.wlan.status()
print('wlan status:{}'.format(status))
return {"action":"device.wlanStatus","data":{"status":status}}
def wlanInfo(self,data):
ip,subnet_mask,gateway,dns = app.wlan.ifconfig()
return {'action':'device.wlanInfo','data':{'ip':ip,'subnet_mask':subnet_mask,'gateway':gateway,'dns':dns}}
def exit(self,data):
sys.exit()
app.__ISRUNING = False
print('sys stop!')
def connectWifi(self,data):
if "ssid" not in data or 'password' not in data:
return {"action":"device.connectwifi",'data':{'code':-1,'msg':'SSID或Password不存在'}}
reset = False
if "reset" in data and data['reset'] : reset = True
ret,wlan = app.connectWifi(data['ssid'], data['password'],reset)
resp = {
"action":"device.connectWifi",
"data":{
"wlan_info":app.wlan.ifconfig(),
'wlan_status':app.wlan.status()
}
}
if ret: resp['code'] = 1
else: resp['code'] = -1
return resp
class gpio:
def __init__(self):
self.pins = {
'pwm':[0,2,5,10,12,13,14,18,19,21,25,27,28,29,33],
'i2c':[0,2,4,5,9,18,19,21,25,26,27],
'switch':[13,12,14,27,26,25,33,32,2,16,17,5,18,19,21,]
}
def pwm(self,data):
if "duty" in data and "pin" in data and data["pin"] in self.pins['pwm']:
freq = 78125
if "freq" in data:
freq = data["freq"]
if freq > 78125: freq = 78125
pwm = PWM(Pin(data["pin"]), freq = freq, duty = data["duty"])
print('pin:{},duty:{},freq:{}'.format(data['pin'],data["duty"],freq))
return {'code':1,'action':'gpio.pwm','data':{'status':1}}
else:
print('no pins')
return {'code':1,'action':'gpio.pwm','data':{'status':-1,'msg':'no pins or duty'}}
def i2c(self,data):
pass
def switch(self,data):
if "switch" in data and "pin" in data and data["pin"] in self.pins['switch']:
switch = True
if not data['switch']:
switch = False
p = Pin(data['pin'],Pin.OUT)
p.value(switch)
def NecIR(self,data):
pass
class bt:
pass
class mqtt:
def __init__(self):
self.__status = False
def init(self,data):
resp = {'code':1,'action':'mqtt.init','data':{'status':-1,'msg':''}}
if 'clientId' not in data:
resp['data']['msg'] = 'not clientId'
return resp
if 'server' not in data:
resp['data']['msg'] = 'not server'
return resp
port,user,password,keepalive,ssl,ssl_params = 0,None,None,60,False,{}
clientId = data['clientId']
server = data['server']
if 'user' in data:user = data['user']
if 'password' in data:password = data['password']
if 'keepalive' in data:keepalive = data['keepalive']
if 'ssl' in data:ssl = data['ssl']
if 'ssl_params' in data:ssl_params = data['ssl_params']
self.__client = MQTTClient(clientId,server,port,user,password,keepalive,ssl,ssl_params)
def connect(self,data):
try:
self.__client.connect()
except Exception as e:
print('MQTT connection error:',e)
return {'code':1,'action':'mqtt.connect','data':{'status':-1,'msg':e}}
def status(self,data):
return self.__status
def close(self,data):
self.__client.disconnect()
print('MQTT closed')
def ping(self,data):
self.__client.ping()
print('MQTT ping')
def publish(self,data):
resp = {'code':1,'action':'mqtt.publish','data':{'status':-1,'msg':''}}
if 'topic' not in data:
resp['data']['msg'] = 'miss param:topic'
return resp
if 'msg' not in data:
resp['data']['msg'] = 'miss param:msg'
return resp
retain,qos = False,0
if 'retain' in data and isinstance(data['retain'], bool):
retain = data['reatain']
if 'qos' in data and isinstance(data['qos'], int):
qos = data['qos']
self.__client.publish(data['topic'],data['msg'],retain,qos)
def subscribe(self,data):
resp = {'code':1,'action':'mqtt.subscribe','data':{'status':-1,'msg':''}}
if 'topic' not in data:
resp['data']['msg'] = 'miss param:topic'
return resp
qos = 0
if 'qos' in data and isinstance(data['qos'], int):qos = data['qos']
self.__client.subscribe(data['topic'],qos)
def processor():
def cb(topic,msg):
try:
msg = json.loads(msg)
except:
msg = {}
print(topic,msg)
app.module['mqtt'].__client.set_callback(cb)
def msg():
t = time.time()
try:
while app.__ISRUNING:
print(app.__ISRUNING)
app.module['mqtt'].__status = True
app.module['mqtt'].__client.check_msg()
if time.time() - t + 1 >= app.module['mqtt'].__client.keepalive:
t = time.time()
app.module['mqtt'].ping({})
time.sleep(0.1)
app.module['mqtt'].close({})
except Exception as e:
print('MQTT ERROR:',e)
app.module['mqtt'].__status = False
if app.config.get('mqtt.autoReconnect',False) == True:
print('MQTT reconnect...')
time.sleep(1)
app.mqttConnect()
_thread.start_new_thread(msg,())
class app:
p = None
wlan = None
__ISRUNING = False
config = config()
module = {
'device':device(),
'gpio':gpio(),
'bt':bt(),
'system':system(),
'mqtt':mqtt()
}
def start():
app.__ISRUNING = True
if app.config.get('subdevice.enabled',False):
rx = app.config.get('subdevice.rx',22)
rx = app.config.get('subdevice.tx',23)
app.subDevice = UART(2, baudrate = 115200, bits = 8, parity = None, rx = rx, tx = tx, timeout = 10,stop = 1)
def subDeviceRecv():
try:
while app.ISRUNING():
if(app.subDevice.any()):
read = json.loads(app.subDevice.read())
if(isinstance(read,dict)):
app.p.write(json.dumps(read))
print('子设备回复:{}'.format(read))
except KeyboardInterrupt:
print('中断执行')
except Exception as e:
print(e)
_thread.start_new_thread(subDeviceRecv, ())
app.wlan = network.WLAN(network.STA_IF)
ssid = app.config.get('wifi.ssid')
password = app.config.get('wifi.password')
active = app.config.get('wifi.active',False)
if ssid and password and active == True:
app.connectWifi(ssid, password)
if app.wlan.status() == 1010:
app.mqttConnect()
def mqttConnect():
try:
mqttConfig = app.config.get('mqtt',None)
if mqttConfig and mqttConfig['autoConnect'] == True:
app.module['mqtt'].init(mqttConfig)
app.module['mqtt'].connect({})
mqtt.processor()
for i in mqttConfig['subscribe']:
app.module['mqtt'].subscribe({'topic':i})
except Exception as e:
print('MQTT exception',e)
def isEsp32():
uname = getattr(os,'uname',None)
if uname == None:return False
sysname,nodename,release,version,machine = uname()
return sysname == "esp32"
def ISRUNING():
return app.__ISRUNING
def msgProcessor(topic,msg):
print('topic:{}'.format(topic))
try:
data = json.loads(msg)
except:
data = {}
print('msg:{}'.format(data))
if 'action' in data and re.match(r'^([a-zA-Z])+\.(\w)+$',data['action']):
action = data['action'].split('.')
if action[0] not in app.module:
print('[{}]模块不支持!'.format(action[0]))
else:
func = getattr(app.module[action[0]],action[1],None)
if not func:
print('[{}]操作不支持!'.format(action[1]))
else:
getData = {}
if 'data' in data and isinstance(data['data'],dict):
getData = data['data']
func(getData)
def uartProcessor(origin):
try:
data = json.loads(origin)
print('msg:{}'.format(data))
except:
print('data:{}'.format(origin))
data = {}
if 'action' in data and re.match(r'^([a-zA-Z])+\.(\w)+$',data['action']):
action = data['action'].split('.')
if action[0] not in app.module:
return {"action":"system.error","data":{"msg":'[{}]模块不支持!'.format(action[0])}}
func = getattr(app.module[action[0]],action[1],None)
if not func:
return {"action":"system.error","data":{"msg":'[{}]操作不支持!'.format(action[1])}}
getData = {}
if 'data' in data and isinstance(data['data'],dict):
getData = data['data']
resp = func(getData)
if isinstance(resp,dict) and 'req_id' in data:
resp['req_id'] = data['req_id']
return resp
def connectWifi(ssid, password,reset = False):
# STAT_IDLE -- 没有连接,没有活动-1000
# STAT_CONNECTING -- 正在连接-1001
# STAT_WRONG_PASSWORD -- 由于密码错误而失败-202
# STAT_NO_AP_FOUND -- 失败,因为没有接入点回复,201
# STAT_GOT_IP -- 连接成功-1010
# STAT_ASSOC_FAIL -- 203
# STAT_BEACON_TIMEOUT -- 超时-200
# STAT_HANDSHAKE_TIMEOUT -- 握手超时-204
if not app.isEsp32():
print('IS NOT ESP32')
return True,app.wlan
if app.wlan == None:
app.wlan = network.WLAN(network.STA_IF)
app.wlan.active(True)
if not app.wlan.isconnected() or reset:
app.wlan.disconnect()
app.wlan.active(True)
app.wlan.connect(ssid,password)
err_code = [200,201,202,203,204]
if app.wlan.status() in err_code:
print('WIFI connection error')
return False,app.wlan
elif app.wlan.status() == 1001:
print('WIFI connection...')
return False,app.wlan
elif app.wlan.status() == 1010:
print('WIFI connection success')
ip,subnet_mask,gateway,dns = app.wlan.ifconfig()
print('WIFI IP:{},MASK:{},GATEWAY:{},DNS:{}'.format(ip,subnet_mask,gateway,dns))
return True,app.wlan
else:
print('WIFI status unknown')
return False,app.wlan
def exit():
app.__ISRUNING = False
print('exit')
sys.exit()
__all__ = ['app','device','gpio','config','system']
还有部分程序来自GitHub开源程序,分别是:MicroWebSrv、MicroWebTemplate、MicroWebSocket,在网上都能找到,这里就不贴了。
程序未完善,权当记录一下过程,勿喷~

